package com.yeziji.common.business.system.service.impl;

import cn.hutool.json.JSONUtil;
import com.yeziji.common.CommonErrorMsg;
import com.yeziji.common.IServiceImpl;
import com.yeziji.common.business.system.dto.SystemRoleReleasesUrlDTO;
import com.yeziji.common.business.system.dto.SystemUserRoleDTO;
import com.yeziji.common.business.system.entity.SystemPermissionEntity;
import com.yeziji.common.business.system.entity.SystemRoleEntity;
import com.yeziji.common.business.system.entity.SystemRolePermissionRelationEntity;
import com.yeziji.common.business.system.entity.SystemUserRoleRelationEntity;
import com.yeziji.common.business.system.entity.table.SystemRoleTableDef;
import com.yeziji.common.business.system.entity.table.SystemUserRoleRelationTableDef;
import com.yeziji.common.business.system.mapper.SystemUserRoleRelationMapper;
import com.yeziji.common.business.system.msg.SystemErrorMsg;
import com.yeziji.common.business.system.service.SystemRoleService;
import com.yeziji.common.business.system.service.SystemUserRoleRelationService;
import com.yeziji.utils.expansion.Asserts;
import com.yeziji.utils.expansion.Lists2;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;

/**
 * 系统用户角色关联表 服务层实现。
 *
 * @author system
 * @since 2023-11-13
 */
@Service
public class SystemUserRoleRelationServiceImpl extends IServiceImpl<SystemUserRoleRelationMapper, SystemUserRoleRelationEntity> implements SystemUserRoleRelationService {
    private static final SystemRoleTableDef SYSTEM_ROLE = SystemRoleTableDef.SYSTEM_ROLE;
    private static final SystemUserRoleRelationTableDef SYSTEM_USER_ROLE_RELATION = SystemUserRoleRelationTableDef.SYSTEM_USER_ROLE_RELATION;
    @Resource
    private SystemRoleService systemRoleService;

    @Override
    public boolean bindUserRole(SystemUserRoleDTO userRoleDTO) {
        Long userId = userRoleDTO.getUserId();
        Long roleId = userRoleDTO.getRoleId();
        // 确保用户与角色存在
        Asserts.isFalse(systemRoleService.queryChain().where(SystemRoleEntity::getId).eq(roleId).exists(), SystemErrorMsg.SYSTEM_ROLE_IS_NOT_EXISTS);
        // 查询是否重复绑定
        SystemUserRoleDTO systemUserRole =
                this.queryChain()
                        .select(SystemUserRoleRelationTableDef.SYSTEM_USER_ROLE_RELATION.ID,
                                SystemRoleTableDef.SYSTEM_ROLE.ID.as("role_id"))
                        .from(SystemUserRoleRelationEntity.class)
                        .join(SystemRoleEntity.class).on((queryWrapper) -> queryWrapper.where(SystemRoleEntity::getId).eq(SystemUserRoleRelationEntity::getRoleId))
                        .where(SystemRoleEntity::getId).eq(Asserts.notNull(roleId, CommonErrorMsg.REQUIRED_DATA_IS_NULL))
                        .and(SystemUserRoleRelationEntity::getUserId).eq(Asserts.notNull(userId, CommonErrorMsg.REQUIRED_DATA_IS_NULL))
                        .oneAs(SystemUserRoleDTO.class);
        Asserts.isNull(systemUserRole, SystemErrorMsg.SYSTEM_USER_ROLE_IS_BOUND);
        return this.save(new SystemUserRoleRelationEntity(userId, roleId));
    }

    @Override
    public List<SystemRoleReleasesUrlDTO> listSystemRoleReleaseUrls() {
        List<SystemRoleReleasesUrlDTO> systemRoleReleasesUrls = this.queryChain()
                .select("role_name", "params as release_urls")
                .from(SystemPermissionEntity.class)
                .join(SystemRolePermissionRelationEntity.class).on((queryWrapper) -> queryWrapper.where(SystemRolePermissionRelationEntity::getPermissionId).eq(SystemPermissionEntity::getId))
                .join(SystemRoleEntity.class).on((queryWrapper) -> queryWrapper.where(SystemRoleEntity::getId).eq(SystemRolePermissionRelationEntity::getRoleId))
                .listAs(SystemRoleReleasesUrlDTO.class);
        filterJsonParams(systemRoleReleasesUrls);

        return systemRoleReleasesUrls;
    }

    @Override
    public List<SystemRoleReleasesUrlDTO> listUserSystemRoleReleaseUrls(Long userId) {
        List<SystemRoleReleasesUrlDTO> systemRoleReleasesUrls = this.queryChain()
                .select("role_name", "params as release_urls")
                .from(SystemPermissionEntity.class)
                .join(SystemRolePermissionRelationEntity.class).on((queryWrapper) -> queryWrapper.where(SystemRolePermissionRelationEntity::getPermissionId).eq(SystemPermissionEntity::getId))
                .join(SystemRoleEntity.class).on((queryWrapper) -> queryWrapper.where(SystemRoleEntity::getId).eq(SystemRolePermissionRelationEntity::getRoleId))
                .join(SystemUserRoleRelationEntity.class).on((queryWrapper) -> queryWrapper.where(SystemUserRoleRelationEntity::getRoleId).eq(SystemRoleEntity::getId))
                .where(SystemUserRoleRelationEntity::getUserId).eq(userId)
                .listAs(SystemRoleReleasesUrlDTO.class);
        filterJsonParams(systemRoleReleasesUrls);

        return systemRoleReleasesUrls;
    }

    @Override
    public List<Long> listUserIdsByRoleId(Long roleId) {
        return this.queryChain()
                .select(SystemUserRoleRelationTableDef.SYSTEM_USER_ROLE_RELATION.USER_ID)
                .where(SystemUserRoleRelationEntity::getRoleId).eq(roleId)
                .listAs(Long.class);
    }

    @Override
    public SystemUserRoleDTO getAsUserRoleByUserId(Long userId) {
        return this.queryChain()
                .select(SYSTEM_USER_ROLE_RELATION.ID, SYSTEM_USER_ROLE_RELATION.USER_ID, SYSTEM_USER_ROLE_RELATION.ROLE_ID)
                .select(SYSTEM_ROLE.ROLE_NAME)
                .join(SystemRoleEntity.class).on((queryWrapper) -> queryWrapper.where(SystemRoleEntity::getId).eq(SystemUserRoleRelationEntity::getRoleId))
                .where(SystemUserRoleRelationEntity::getUserId).eq(userId)
                .oneAs(SystemUserRoleDTO.class);
    }

    /**
     * permission params 中可能存在 JSON 字符串或獨立字符串，这里过滤进行过滤
     *
     * @param systemRoleReleasesUrls 系统角色放行地址
     */
    private static void filterJsonParams(List<SystemRoleReleasesUrlDTO> systemRoleReleasesUrls) {
        // 获取放行地址时过滤掉是 JSON 字符串的值
        for (SystemRoleReleasesUrlDTO systemRoleReleasesUrl : systemRoleReleasesUrls) {
            List<String> releaseUrls = systemRoleReleasesUrl.getReleaseUrls();
            if (Lists2.isNotEmpty(releaseUrls)) {
                for (int i = 0; i < releaseUrls.size(); i++) {
                    String params = releaseUrls.get(i);
                    if (JSONUtil.isTypeJSON(params)) {
                        releaseUrls.remove(i--);
                    } else if (!params.contains("/")) {
                        releaseUrls.remove(i--);
                    }
                }
            }
        }
    }
}
